package br.com.foxinline.manager.criar;

import br.com.foxinline.enums.AplicacaoCampo;
import br.com.foxinline.enums.StatusProtocolo;
import br.com.foxinline.enums.TipoDesconto;
import br.com.foxinline.enums.TipoPessoa;
import br.com.foxinline.enums.TipoProtocolo;
import br.com.foxinline.modelo.Ato;
import br.com.foxinline.modelo.AtoCampo;
import br.com.foxinline.modelo.EmolumentoItem;
import br.com.foxinline.modelo.Parcela;
import br.com.foxinline.modelo.Pessoa;
import br.com.foxinline.modelo.Protocolo;
import br.com.foxinline.modelo.ProtocoloCampo;
import br.com.foxinline.modelo.ProtocoloItem;
import br.com.foxinline.servico.AtoServico;
import br.com.foxinline.servico.AtoCampoServico;
import br.com.foxinline.servico.PessoaServico;
import br.com.foxinline.servico.ProtocoloServico;
import br.com.foxinline.servico.EmolumentoItemServico;
import br.com.foxinline.utilitario.Caracteres;
import br.com.foxinline.utilitario.Mensagem;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

/**
 *
 * @author cadomeireles
 */
@ViewScoped
@ManagedBean
public class ManagerCriarProtocolo implements Serializable {

    @EJB
    ProtocoloServico protocoloServico;
    @EJB
    PessoaServico pessoaServico;
    @EJB
    AtoServico atoServico;
    @EJB
    EmolumentoItemServico emolumentoItemServico;
    @EJB
    AtoCampoServico atoCampoServico;
    private Protocolo protocolo;
    private ProtocoloItem protocoloItem;
    private List<ProtocoloItem> protocoloItens;
    private EmolumentoItem emolumentoItem;
    private List<ProtocoloCampo> protocoloCampos;
    private Pessoa pessoaPesquisar;
    private Pessoa pessoaSelecionada;
    private List<Pessoa> pessoas;
    Parcela parcela;
    private List<Parcela> parcelas;
    private Ato ato;
    private List<AtoCampo> atoCampos;
    private BigDecimal valorTotalProtocolo;
    private boolean emAberto;
    private String editarId;

    @PostConstruct
    public void init() {
        instanciar();
        delegar();
    }

    private void instanciar() {
        this.protocolo = new Protocolo();
        this.protocolo.setTipoProtocolo(TipoProtocolo.PROTOCOLO);
        this.protocolo.setCliente(new Pessoa());
        this.protocolo.setValorTotalCartorio(BigDecimal.ZERO);
        this.protocolo.setValorTotalFermojupi(BigDecimal.ZERO);

        this.parcela = new Parcela();
        this.parcelas = new ArrayList<Parcela>();

        this.protocoloItens = new ArrayList<ProtocoloItem>();

        instanciarItens();

        instanciarPessoas();

        this.valorTotalProtocolo = BigDecimal.ZERO;

        this.emAberto = true;
    }

    private void delegar() {
        Map<String, String> parametros = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        this.editarId = parametros.get("protocoloId");

        if (this.editarId != null) {
            this.protocolo = protocoloServico.pesquisar(Long.parseLong(editarId));
            this.protocolo.setProtocoloItems(protocoloServico.obterItens(this.protocolo));
            this.protocoloItens.addAll(this.protocolo.getProtocoloItems());
            this.parcelas = protocoloServico.obterParcelas(this.protocolo);

            this.valorTotalProtocolo = this.protocolo.getValorTotalCartorio().add(this.protocolo.getValorTotalFermojupi());
        }
    }

    private void instanciarItens() {
        this.ato = new Ato();
        this.atoCampos = new ArrayList<AtoCampo>();
        this.protocoloCampos = new ArrayList<ProtocoloCampo>();
        this.protocoloItem = new ProtocoloItem();
        this.emolumentoItem = new EmolumentoItem();
    }

    private void instanciarPessoas() {
        this.pessoaPesquisar = new Pessoa();
        this.pessoaPesquisar.setTipoPessoa(TipoPessoa.FISICA);
        this.pessoas = new ArrayList<Pessoa>();
    }

    public void limparPessoas() {
        this.pessoaPesquisar.setNome(null);
        this.pessoaPesquisar.setCpf(null);
        this.pessoaPesquisar.setCnpj(null);
        this.pessoas = new ArrayList<Pessoa>();
    }

    public String reprAto(Ato ato) {
        if (ato.getCodigo() != null) {
            return ato.getCodigo().concat(" - ").concat(ato.getDescricao());
        } else {
            return "";
        }
    }

    public void pesquisarPessoas() {
        this.pessoas = pessoaServico.pesquisarCliente(this.pessoaPesquisar);
    }

    public void selecionarPessoa() {
        this.protocolo.setCliente(this.pessoaSelecionada);
        limparPessoas();
    }

    public List<Ato> autocompletarAto(String query) {
        return atoServico.autocompletar(query);
    }

    public void obterValorTotal() {
        this.protocolo.setValorDevolvido(this.valorTotalProtocolo);
    }

    public void cancelar() {
        this.protocolo.setStatusProtocolo(StatusProtocolo.CANCELADO);
        this.protocolo.setDataCancelamento(new Date());

        protocoloServico.atualizar(this.protocolo);

        Mensagem.messagemInfo("Protocolo cancelado!");
    }

    public void limparDadosCancelar() {
        this.protocolo.setValorDevolvido(null);
    }

    public void gerarCampos() {
        this.protocoloCampos = new ArrayList<ProtocoloCampo>();

        this.atoCampos = atoCampoServico.pesquisar(this.ato);

        for (AtoCampo campo : this.atoCampos) {
            ProtocoloCampo protocoloCampo = new ProtocoloCampo();
            protocoloCampo.setAtoCampo(campo);
            this.protocoloCampos.add(protocoloCampo);
        }
    }

    public void removerProtocoloItem(ProtocoloItem item) {
        this.protocolo.setValorTotalCartorio(this.protocolo.getValorTotalCartorio().subtract(item.getValorCartorio()));
        this.protocolo.setValorTotalFermojupi(this.protocolo.getValorTotalFermojupi().subtract(item.getValorFermojupi()));
        this.valorTotalProtocolo = this.valorTotalProtocolo.subtract(item.getValor());

        this.protocoloItens.remove(item);
    }

    public void adicionarProtocoloItem() {

        // Ato sem campos relacionados, trazer o item do emulomento correspondente
        if (this.protocoloCampos.isEmpty()) {

            try {
                this.emolumentoItem = emolumentoItemServico.pesquisar(this.ato);
                this.protocoloItem.setValor(this.emolumentoItem.getValorTotal());

                this.protocoloItem.setAtoItem(this.ato);
                this.protocoloItens.add(this.protocoloItem);

                calcularTotaisEmolumento();
            } catch (Exception e) {
                Mensagem.messagemWarn("Não existe nenhum item na tabela de Emolumentos para esse Ato.");
            }

            // Ato com campos relacionados, trazer o item do emulomento correspondente
            // e com o valor dos campos
        } else {
            for (ProtocoloCampo protocoloCampo : this.protocoloCampos) {
                // Campo usado como filtro na tabela de emolumentos
                if (protocoloCampo.getAtoCampo().getAplicacao() == AplicacaoCampo.FILTRO) {
                    try {
                        this.emolumentoItem = emolumentoItemServico.pesquisar(this.ato, new BigDecimal(protocoloCampo.getValor()));
                        this.protocoloItem.setValor(this.emolumentoItem.getValorTotal());

                        this.protocoloItem.setAtoItem(this.ato);
                        this.protocoloItens.add(this.protocoloItem);

                        calcularTotaisEmolumento();
                    } catch (Exception e) {
                        Mensagem.messagemWarn("Não existe nenhum item na tabela de Emolumentos para esse Ato com o valor digitado.");
                    }
                    // Campo usado como valor do ato
                } else if (protocoloCampo.getAtoCampo().getAplicacao() == AplicacaoCampo.VALOR) {
                    this.protocoloItem.setValor(new BigDecimal(protocoloCampo.getValor()));

                    this.protocoloItem.setAtoItem(this.ato);
                    this.protocoloItens.add(this.protocoloItem);

                    calcularTotaisMaster();
                }
            }
        }

        instanciarItens();
    }

    public void calcularTotaisEmolumento() {
        this.protocoloItem.setValorCartorio(this.emolumentoItem.getValorCartorio());
        this.protocoloItem.setValorFermojupi(this.emolumentoItem.getValorFermojupi());

        this.protocolo.setValorTotalCartorio(this.protocolo.getValorTotalCartorio().add(this.emolumentoItem.getValorCartorio()));
        this.protocolo.setValorTotalFermojupi(this.protocolo.getValorTotalFermojupi().add(this.emolumentoItem.getValorFermojupi()));
        this.protocolo.setValorCartorio(this.protocolo.getValorTotalCartorio());
        this.setValorTotalProtocolo(this.valorTotalProtocolo.add(this.emolumentoItem.getValorTotal()));
    }

    public void calcularTotaisMaster() {
        this.protocoloItem.setValorCartorio(this.protocoloItem.getValor().multiply(new BigDecimal(0.9)));
        this.protocoloItem.setValorFermojupi(this.protocoloItem.getValor().multiply(new BigDecimal(0.1)));

        this.protocolo.setValorTotalCartorio(this.protocolo.getValorTotalCartorio().add(this.protocoloItem.getValorCartorio()));
        this.protocolo.setValorTotalFermojupi(this.protocolo.getValorTotalFermojupi().add(this.protocoloItem.getValorFermojupi()));
        this.protocolo.setValorCartorio(this.protocolo.getValorTotalCartorio());
        this.setValorTotalProtocolo(this.valorTotalProtocolo.add(this.protocoloItem.getValor()));
    }

    public void calcularDesconto() {
        this.protocolo.setValorTotalCartorio(this.protocolo.getValorCartorio());

        if (this.protocolo.getTipoDesconto() == TipoDesconto.DINHEIRO) {
            this.protocolo.setValorTotalCartorio(this.protocolo.getValorTotalCartorio().subtract(this.protocolo.getDescontoDinheiro()));
            this.valorTotalProtocolo = this.protocolo.getValorTotalCartorio().add(this.protocolo.getValorTotalFermojupi());
        } else if (this.protocolo.getTipoDesconto() == TipoDesconto.PORCENTAGEM) {
            BigDecimal desconto = this.protocolo.getValorTotalCartorio().multiply(new BigDecimal(this.protocolo.getDescontoPorcentagem()));
            this.protocolo.setValorTotalCartorio(this.protocolo.getValorTotalCartorio().subtract(desconto));
            this.valorTotalProtocolo = this.protocolo.getValorTotalCartorio().add(this.protocolo.getValorTotalFermojupi());
        }
    }

    public void limparDesconto() {
        this.protocolo.setValorTotalCartorio(this.protocolo.getValorCartorio());
        this.valorTotalProtocolo = this.protocolo.getValorTotalCartorio().add(this.protocolo.getValorTotalFermojupi());
        this.protocolo.setDescontoDinheiro(null);
        this.protocolo.setDescontoPorcentagem(null);
    }

    public BigDecimal aReceber() {
        BigDecimal valorPago = BigDecimal.ZERO;
        for (Parcela p : this.parcelas) {
            if (p.isQuitada()) {
                valorPago = valorPago.add(p.getValorAPagar());
            }
        }
        return this.valorTotalProtocolo.subtract(valorPago);
    }

    public void adicionarParcela() {
        this.parcela.setQuitada(!this.emAberto);
        this.emAberto = true;
        this.parcelas.add(this.parcela);
        this.parcela = new Parcela();
        aReceber();
    }

    public void pagarParcela(Parcela parcela) {
        this.parcelas.remove(parcela);
        parcela.setQuitada(true);
        this.parcelas.add(parcela);
    }

    public void editarParcela(Parcela parcela) {
        this.parcela = parcela;
        removerParcela(parcela);
    }

    public void removerParcela(Parcela parcela) {
        this.parcelas.remove(parcela);
    }

    public void salvar() {

        String mensagem;

        for (ProtocoloItem item : this.protocoloItens) {
            if (item.getAtoItem().getPrazo() != null && item.getAtoItem().getPrazo() > this.protocolo.getPrazo()) {
                this.protocolo.setPrazo(item.getAtoItem().getPrazo());
            }
        }

        this.protocolo.setProtocoloItems(this.protocoloItens);

        this.protocolo.setParcelas(this.parcelas);


        // salvar protocolo
        if (this.protocolo.getId() == null) {
            protocoloServico.salvar(this.protocolo);
            init();
            mensagem = "Protocolo cadastrado com sucesso!";

            // atualizar protocolo
        } else {
            protocoloServico.atualizar(this.protocolo);
            mensagem = "Protocolo atualizado com sucesso!";
        }

        Mensagem.messagemInfo(mensagem);
    }

    public void gerarRecibo() {
        protocoloServico.gerarRecibo(this.protocolo, this.getValorTotalProtocolo(), this.protocolo.getProtocoloItems());
    }    

    public void limparDadosEntrega() {
        this.protocolo.setCpfEntrega(new String());
        this.protocolo.setNomeEntrega(new String());
    }

    public void entregar() {
        this.protocolo.setStatusProtocolo(StatusProtocolo.ENTREGUE);
        this.protocolo.setDataEntrega(new Date());
        this.protocolo.setCpfEntrega(Caracteres.removecaracter(this.protocolo.getCpfEntrega()));
        protocoloServico.atualizar(this.protocolo);

        Mensagem.messagemInfo("Protocolo entrege!");
    }

    public String obterInteressado() {
        Pessoa pessoa = this.protocolo.getCliente();

        if (pessoa.getTipoPessoa() != null) {
            if (pessoa.getTipoPessoa() == TipoPessoa.FISICA) {
                return pessoa.getNome() + ", CPF " + adicionarMascaraCPF(pessoa.getCpf());
            } else {
                return pessoa.getRazaoSocial() + ", CNPJ " + adicionarMascaraCNPJ(pessoa.getCnpj());
            }
        } else {
            return "";
        }

    }

    public String adicionarMascaraCNPJ(String string) {
        return Caracteres.adicionarMascara(string, Caracteres.cnpjMask);
    }

    public String adicionarMascaraCPF(String string) {
        return Caracteres.adicionarMascara(string, Caracteres.cpfMask);
    }

    public Ato getAto() {
        return ato;
    }

    public void setAto(Ato ato) {
        this.ato = ato;
    }

    public Pessoa getPessoaPesquisar() {
        return pessoaPesquisar;
    }

    public void setPessoaPesquisar(Pessoa pessoaPesquisar) {
        this.pessoaPesquisar = pessoaPesquisar;
    }

    public List<Pessoa> getPessoas() {
        return pessoas;
    }

    public void setPessoas(List<Pessoa> pessoas) {
        this.pessoas = pessoas;
    }

    public Protocolo getProtocolo() {
        return protocolo;
    }

    public void setProtocolo(Protocolo protocolo) {
        this.protocolo = protocolo;
    }

    public ProtocoloItem getProtocoloItem() {
        return protocoloItem;
    }

    public void setProtocoloItem(ProtocoloItem protocoloItem) {
        this.protocoloItem = protocoloItem;
    }

    public List<ProtocoloItem> getProtocoloItens() {
        return protocoloItens;
    }

    public void setProtocoloItens(List<ProtocoloItem> protocoloItens) {
        this.protocoloItens = protocoloItens;
    }

    public EmolumentoItem getEmolumentoItem() {
        return emolumentoItem;
    }

    public void setEmolumentoItem(EmolumentoItem emolumentoItem) {
        this.emolumentoItem = emolumentoItem;
    }

    public Pessoa getPessoaSelecionada() {
        return pessoaSelecionada;
    }

    public void setPessoaSelecionada(Pessoa pessoaSelecionada) {
        this.pessoaSelecionada = pessoaSelecionada;
    }

    public BigDecimal getValorTotalProtocolo() {
        return valorTotalProtocolo;
    }

    public void setValorTotalProtocolo(BigDecimal valorTotalProtocolo) {
        this.valorTotalProtocolo = valorTotalProtocolo;
    }

    public List<AtoCampo> getAtoCampos() {
        return atoCampos;
    }

    public void setAtoCampos(List<AtoCampo> atoCampos) {
        this.atoCampos = atoCampos;
    }

    public List<ProtocoloCampo> getProtocoloCampos() {
        return protocoloCampos;
    }

    public void setProtocoloCampos(List<ProtocoloCampo> protocoloCampos) {
        this.protocoloCampos = protocoloCampos;
    }

    public List<Parcela> getParcelas() {
        return parcelas;
    }

    public void setParcelas(List<Parcela> parcelas) {
        this.parcelas = parcelas;
    }

    public Parcela getParcela() {
        return parcela;
    }

    public void setParcela(Parcela parcela) {
        this.parcela = parcela;
    }

    public boolean isEmAberto() {
        return emAberto;
    }

    public void setEmAberto(boolean emAberto) {
        this.emAberto = emAberto;
    }
}
